<template>
	<view class="container">
		<!-- 公共组件-每个页面必须引入 -->
		<public-module></public-module>
		<!-- 添加开始面试蒙版 -->
		<view class="start-mask" v-if="!isStarted">
			<view v-if="urlParams.type == 1">
				<view class="start-tips" v-if="showPlayNotAllowedTip">
					点击按钮开始面试并启用声音
				</view>
				<button class="start-btn" @click="startInterview">开始面试</button>
			</view>
			<view v-else>
				<view class="start-tips" v-if="showPlayNotAllowedTip">
					点击按钮语音生成简历并启用声音
				</view>
				<button class="start-btn" @click="startInterview">语音生成简历</button>
			</view>
		</view>

		<!-- 虚拟人视频区域 -->
		<view class="virtual-human-container">

			<view class="preview-area" v-if="urlParams.type == 1">
				<view class="sp"></view>
				<!-- 添加录制控制按钮 -->
				<view class="record-controls">
					<button :class="['record-btn', { 'recording': isH5Recording }]" @click="toggleRecording">
						{{ isH5Recording ? '停止录制' : '开始录制' }}
					</button>
				</view>
			</view>

			<!-- 聊天消息列表 -->
			<view class="chat-list">
				<scroll-view scroll-y class="scroll-area" :scroll-top="scrollTop" :scroll-with-animation="true">
					<view v-for="(msg, index) in chatMessages" :key="index" :class="['message-item', msg.type]">
						<text class="message-content">{{ msg.content }}</text>
					</view>
				</scroll-view>
			</view>

			<view class="wrapper" ref="wrapper">
				<text v-if="loading" style="color: white;">加载中...</text>
			</view>

			<!-- 交互控制区域 -->
			<view class="interaction-area">
				<!-- 文本输入区域 -->
				<!-- <view class="text-input">
					<input v-model="inputText" type="text" placeholder="输入文字与虚拟人对话" @confirm="sendText" />
					<button @click="sendText">发送</button>
				</view> -->

				<!-- 语音交互按钮 -->
				<view class="voice-interaction" v-if="urlParams.type == 1">
					<div class="voice-icon" 
						 :class="{ 'recording': isRecording }"
						 @touchstart.prevent="startAudioRecording"
						 @touchend.prevent="stopAudioRecording"
						 @touchmove.prevent
						 style="background-image: url('/static/dati/mine_dz_tjdz_yysb_icon.png')">
					</div>
					<text class="voice-tip">{{ isRecording ? '松开结束' : '按住说话' }}</text>
				</view>

				<view class="voice-interaction" v-else>
					<div class="voice-icon" 
						 :class="{ 'recording': isRecording }"
						 @touchstart.prevent="startAudioRecording"
						 @touchend.prevent="stopAudioRecording"
						 @touchmove.prevent
						 style="background-image: url('/static/dati/mine_dz_tjdz_yysb_icon.png')">
					</div>
					<text class="voice-tip">{{ isRecording ? '松开结束' : '按住说话' }}</text>
				</view>
				<!-- <div class="voice-interaction">
					<div class="voice-icon" :class="{ recording: isRecording }" @touchstart="startAudioRecording"
						@touchend="stopAudioRecording">
					</div>
					<div class="voice-tip">{{ isRecording ? '松开结束' : '按住说话' }}</div>
				</div> -->
			</view>
		</view>
	</view>
</template>

<script>
import $http from '@/config/requestConfig'
import AvatarPlatform, {
	PlayerEvents,
	SDKEvents,
} from './sdk/3.0.0.1002/index.js'

export default {
	data() {
		return {
			audioContext: null,
			audioInput: null,
			audioChunks: [],
			isRecording: false,
			inputText: '',
			loading: true,
			avatarPlatform: null,
			player: null,
			baiduConfig: {
			  apiKey: 'oKyKu3UlblS5RZBdih2pe7yJ',
			  secretKey: 'zn4GPjeqkFSRljbnahtHzpSG9q320tlA',
			  accessToken: '' // 用于存储获取到的 access token
			},
			apiConfig: {
				appId: 'f782b5a8',
				apiKey: 'f8fbc4d6cd11823a79ad19eb51adc63e',
				apiSecret: 'NDY4MjNiZjMxN2YxOGJmYmQ1ZGVkOGU3',
				virtualHumanId: '',
				sceneId: '211368118243692544', 
				vcn: ''
			},
			chatMessages: [], // 聊天消息列表
			scrollTop: 0, // 滚动位置
			questionList: [], // 存储问题列表
			currentQuestionIndex: 0, // 当前问题索引
			recorder: null, // 录音器实例
			isProcessing: false, // 添加处理状态标记
			videoRecorder: null, // 视频录制器
			videoPath: '', // 录制的视频路径
			screenRecorder: null, // 屏幕录制器
			mediaRecorder: null,
			recordedChunks: [],
			recordedVideoUrl: null,
			stream: null,
			isH5Recording: false, // 用于H5录制状态
			isStarted: false, // 添加开始状态控制
			showPlayNotAllowedTip: false, // 添加提示控制
			urlParams: {
				qyid: '',
				msid: '',
				qzid: '',
				subid: '',
				jobid: '',
				type: '', //0录音1视频
				posname:''
			},
			recordStartTime: null, // 添加录音开始时间
			baiduParams: [], // 存储数字人和用户对话的数组
			isTranscribing: false, // 添加转写状态标记
			inactivityTimer: null, // 添加定时器变量
			inactivityTimeout: 300000, // 5分钟 = 5 * 60 * 1000 毫秒
			allAnswers: [],
		}
	},

	async onLoad() {
		this.getBaiduToken()
		this.getUrlParams();
		// this.isStarted = true;
		// uni.showLoading({
		// 	title: '正在初始化...'
		// });

		// AvatarPlatform.setLogLevel(1)
		// try {
		// 	await this.getWenti()
		// 	await this.getxingxiang()
		// 	await this.initAvatarSDK()
		// 	await new Promise(resolve => setTimeout(resolve, 1000))
		// 	await this.readNextQuestion()
		// 	await this.initCamera()
		// } catch (error) {
		// 	console.error('初始化失败:', error)
		// 	uni.showToast({
		// 		title: '初始化失败，请重试',
		// 		icon: 'none'
		// 	})
		// } finally {
		// 	uni.hideLoading();
		// }
	},

	methods: {
		// 获取百度 access token
		async getBaiduToken() {
		  try {
		    const res = await uni.request({
		      url: `/szbjs/oauth/2.0/token?grant_type=client_credentials&client_id=${this.baiduConfig.apiKey}&client_secret=${this.baiduConfig.secretKey}`,
		      method: 'GET',
		      header: {
		        'Content-Type': 'application/json',
		        'Accept': 'application/json'
		      }
		    })
		    console.log('token响应:', res[1])
		    if (res[1].data && res[1].data.access_token) {
		      this.baiduConfig.accessToken = res[1].data.access_token
		      console.log('获取百度token成功')
		    } else {
		      console.error('获取token失败:', res.data)
		      uni.showToast({
		        title: '初始化语音服务失败',
		        icon: 'none'
		      })
		    }
		  } catch (error) {
		    console.error('获取百度token失败:', error)
		    uni.showToast({
		      title: '初始化语音服务失败',
		      icon: 'none'
		    })
		  }
		},
		// 添加长按开始录音方法
		startAudioRecording() {
			this.isRecording = true;
			navigator.mediaDevices.getUserMedia({ audio: true }).then(stream => {
				this.stream = stream;
				this.mediaRecorder = new MediaRecorder(stream);
				this.audioChunks = [];
				this.mediaRecorder.ondataavailable = (e) => {
					if (e.data.size > 0) this.audioChunks.push(e.data);
				};
				this.mediaRecorder.onstop = async () => {
					console.log('onstop触发', this.currentQuestionIndex, this.questionList);
					console.log('questionList 长度:', this.questionList.length);
					try {
						const recordDuration = Date.now() - this.recordStartTime;
						if (recordDuration < 2000) {
							uni.showToast({
								title: '回答时间太短，请至少说话2秒',
								icon: 'none',
								duration: 2000
							});
							this.audioChunks = [];
							return;
						}
						const audioBlob = new Blob(this.audioChunks, { type: 'audio/webm;codecs=opus' });
						await this.sendToBaiduAPI(audioBlob);
						const response = await uni.request({
							url: '/baiduapi/server_api',
							method: 'POST',
							header: { 'Content-Type': 'application/json' },
							data: {
								format: 'pcm',
								rate: 16000,
								channel: 1,
								token: this.baiduConfig.accessToken,
								speech: this.base64Audio,
								len: this.pcmLength,
								cuid: 'baidu_workshop',
								dev_pid: 1537,
								_t: Date.now()
							}
						});
						let recognizedText = '';
						if (response[1].data && response[1].data.result) {
							recognizedText = response[1].data.result[0];
							const cleanedText = this.removeDuplicateText(recognizedText);
							this.addMessage(cleanedText, 'sent');
							if (this.urlParams.type == 0) {
								this.allAnswers.push(cleanedText);
							}
							if (this.urlParams.type == 1) {
								const currentQuestion = this.questionList[this.currentQuestionIndex];
								this.baiduParams.push({
									question: currentQuestion.problem,
									answer: cleanedText
								});
							}
							if (this.urlParams.type == 0) {
								if (this.currentQuestionIndex < this.questionList.length - 1) {
									this.currentQuestionIndex++;
									console.log('准备进入下一题', this.currentQuestionIndex, this.questionList[this.currentQuestionIndex]);
									await this.readNextQuestion();
								} else {
									// 最后一题，先上传音频文件，再调用audioFile，text为所有回答拼接
									try {
										// 上传音频文件
										const audioUploadResult = await new Promise((resolve, reject) => {
											const xhr = new XMLHttpRequest();
											const formData = new FormData();
											formData.append('file', new File([audioBlob], 'recording.wav', { type: 'audio/wav' }));
											formData.append('biz', 'ZJG');
											xhr.open('POST', 'https://www.zjgrc.com/zjgai/ai/sys/common/upload', true);
											xhr.setRequestHeader('Accept', 'application/json, text/plain, */*');
											xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
											xhr.onload = function () {
												if (xhr.status === 200) {
													resolve(JSON.parse(xhr.responseText));
												} else {
													reject(new Error(`上传失败: ${xhr.status} ${xhr.statusText}`));
												}
											};
											xhr.onerror = () => reject(new Error('网络错误'));
											xhr.send(formData);
										});
										// 拼接所有回答
										const allText = this.allAnswers.join('\n');
										// 调用audioFile接口
										await this.$http.post('/aiResume/audioFile', {
											"path": audioUploadResult.message,
											"text": allText,
											"subid": this.urlParams.subid,
											"qzid": this.urlParams.qzid,
											"sign": "inuDFvsXRw3d+7MV7qlpibR7mlUiCeQ9JpShspyO4pAj7VaNIiM90IBWiJyKPTI/k1nB+RvnGjUM0YBtzELV2tkJsX6i1G6QL8AY+IDomBWr5xEzrIPH/JurAEp0+q1EuI9mL6OhOuloIl52CqDNmVazSXlrPzm7SUWWOzefUXg="
										});
										uni.showToast({
											title: '面试完成，请关闭当前页面',
											icon: 'success'
										});
									} catch (error) {
										console.error('音频上传或保存失败:', error);
										uni.showToast({
											title: '音频上传失败',
											icon: 'none'
										});
									}
								}
							} else if (this.urlParams.type == 1) {
								// type=1 每次都自动提问下一句
								if (this.currentQuestionIndex < this.questionList.length - 1) {
									this.currentQuestionIndex++;
									console.log('type=1进入下一题', this.currentQuestionIndex, this.questionList[this.currentQuestionIndex]);
									await this.readNextQuestion();
								} else {
									// type=1 的最后一题逻辑：上传视频并跳转结果页
									if (this.isH5Recording && this.mediaRecorder) {
										try {
											// 停止视频录制
											const videoBlob = new Blob(this.recordedChunks, {
												type: 'video/webm'
											});
											// 上传视频文件
											const uploadResult = await new Promise((resolve, reject) => {
												const xhr = new XMLHttpRequest();
												const formData = new FormData();
												formData.append('file', new File([videoBlob], 'recording.mp4', { type: 'video/mp4' }));
												formData.append('biz', 'ZJG');
												xhr.open('POST', 'https://www.zjgrc.com/zjgai/ai/sys/common/upload', true);
												xhr.setRequestHeader('Accept', 'application/json, text/plain, */*');
												xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
												xhr.onload = function() {
													if (xhr.status === 200) {
														resolve(JSON.parse(xhr.responseText));
													} else {
														reject(new Error(`上传失败: ${xhr.status} ${xhr.statusText}`));
													}
												};
												xhr.onerror = () => reject(new Error('网络错误'));
												xhr.send(formData);
											});
											// 如果上传成功，调用业务接口
											if (uploadResult.message) {
												const res = await this.$http.post('/aiKnowleH/uploldFile', {
													"questions":this.baiduParams,
													"path": uploadResult.message,
													"subid": this.urlParams.subid,
													"qzid": this.urlParams.qzid,
													"jobid": this.urlParams.jobid,
													"sign": "inuDFvsXRw3d+7MV7qlpibR7mlUiCeQ9JpShspyO4pAj7VaNIiM90IBWiJyKPTI/k1nB+RvnGjUM0YBtzELV2tkJsX6i1G6QL8AY+IDomBWr5xEzrIPH/JurAEp0+q1EuI9mL6OhOuloIl52CqDNmVazSXlrPzm7SUWWOzefUXg="
												});
												console.log('视频处理完成:', res);
												// 显示加载动画
												uni.showLoading({
													title: 'Ai分析中~',
													mask: true
												});
												try {
													uni.hideLoading();
													console.log('开始跳转到结果页面...');
													const url = `https://www.zjgrc.com/aiinterviewresult?subid=${this.urlParams.subid}&posname=${this.urlParams.posname}`;
													console.log('跳转URL:', url);
													try {
														uni.navigateTo({
															url: url,
															fail: (err) => {
																console.log('uni.navigateTo 失败:', err);
																window.location.replace(url);
															}
														});
													} catch (error) {
														console.log('跳转失败，尝试使用 window.open:', error);
														window.open(url, '_self');
													}
												} catch (error) {
													console.error('跳转过程出错:', error);
													uni.showToast({
														title: '跳转失败，请手动刷新页面',
														icon: 'none',
														duration: 3000
													});
												}
											}
											// 停止录制
											this.mediaRecorder.stop();
											this.isH5Recording = false;
										} catch (error) {
											console.error('视频处理失败:', error);
											uni.showToast({
												title: '处理失败，请重试',
												icon: 'none'
											});
										}
									}
								}
							}
						} else {
							uni.showToast({
								title: '语音识别失败，请重试',
								icon: 'none'
							});
						}
						this.audioChunks = [];
					} catch (e) {
						console.error('onstop error', e);
					}
				};
				this.mediaRecorder.start();
				this.recordStartTime = Date.now();
				console.log('开始录音');
			}).catch(error => {
				console.error('录音初始化失败:', error);
				uni.showToast({
					title: '无法访问麦克风，请确保已授予权限',
					icon: 'none'
				});
			});
		},
		// 停止音频录制
		stopAudioRecording() {
			this.isRecording = false;
			if (this.mediaRecorder && this.mediaRecorder.state === 'recording') {
				this.mediaRecorder.stop();
			}
		},
		async getxingxiang() {
			const res = await this.$http.get('/aiKnowleH/queryBySzr')
			console.log(res, "xiangxiang")
			this.apiConfig.virtualHumanId = res.result.szrid
			this.apiConfig.vcn = res.result.audio
		},
		async getWenti() {
			try {
				const res = await this.$http.post('/aiKnowleH/queryByQyIdtoList', {
					"qyid": this.urlParams.qyid,
					"msid": this.urlParams.msid,
					"jobid":this.urlParams.jobid,
					"sign": "inuDFvsXRw3d+7MV7qlpibR7mlUiCeQ9JpShspyO4pAj7VaNIiM90IBWiJyKPTI/k1nB+RvnGjUM0YBtzELV2tkJsX6i1G6QL8AY+IDomBWr5xEzrIPH/JurAEp0+q1EuI9mL6OhOuloIl52CqDNmVazSXlrPzm7SUWWOzefUXg="
				})

				console.log('问题列表:', res)
				if (res.result && res.result.length > 0) {
					this.questionList = res.result
				}else{
					this.questionList = [
						{
							"problem":'请先简短的介绍一下自己?'
						},
						{
							"problem":'为什么选择这个岗位?'
						},
						{
							"problem":'你觉得这个岗位最重要的能力是什么?	'
						},
						{
							"problem":'如果发现工作中无法解决的问题，你会怎么做?	'
						},
						{
							"problem":'你对我们公司有了解吗?	'
						},
						{
							"problem":'	你的期望薪资是多少？'
						}
					]
				}
			} catch (error) {
				console.error('获取问题失败:', error)
			}
		},

		async readNextQuestion() {
			console.log('readNextQuestion', this.currentQuestionIndex, this.questionList[this.currentQuestionIndex]);
			if (this.currentQuestionIndex < this.questionList.length) {
				const question = this.questionList[this.currentQuestionIndex];
				this.addMessage(question.problem, 'received');
				// 只在 type=1 时调用 writeText
				if (this.urlParams.type == 1 && this.avatarPlatform && typeof this.avatarPlatform.writeText === 'function') {
					try {
						await this.avatarPlatform.writeText(question.problem, {
							avatar_dispatch: {
								interactive_mode: 1
							}
						});
					} catch (error) {
						console.error('朗读问题失败:', error);
						uni.showToast({
							title: '朗读失败，请重试',
							icon: 'none'
						});
					}
				}
			}
		},

		async initAvatarSDK() {
			console.log(this.apiConfig,"this.apiConfigthis.apiConfig")
			try {
				console.log('开始初始化SDK...')

				// 1. 创建实例，添加基本配置
				this.avatarPlatform = new AvatarPlatform({
					useInlinePlayer: true // 启用内置播放器
				})

				// 2. 设置API信息
				this.avatarPlatform.setApiInfo({
					appId: this.apiConfig.appId,
					apiKey: this.apiConfig.apiKey,
					apiSecret: this.apiConfig.apiSecret,
					sceneId: this.apiConfig.sceneId // 添加场景ID
				})

				// 3. 设置全局参数
				this.avatarPlatform.setGlobalParams({
					stream: {
						protocol: 'xrtc'
					},
					avatar: {
						avatar_id: this.apiConfig.virtualHumanId
					},
					tts: {
						vcn: this.apiConfig.vcn
					}
				})
				console.log(this.apiConfig,"this.apiConfig")
				// 4. 设置事件监听
				this.setupSDKEvents()

				// 5. 等待DOM渲染完成
				await this.$nextTick()

				// 6. 发起连接
				const wrapper = document.querySelector('.wrapper')
				if (!wrapper) {
					throw new Error('找不到视频容器元素')
				}

				await this.avatarPlatform.start({
					wrapper: wrapper
				})

				// 7. 获取播放器实例
				this.player = this.avatarPlatform.player || this.avatarPlatform.createPlayer()

				// 8. 设置播放器事件
				if (this.player) {
					this.setupPlayerEvents()
				}

				console.log('SDK初始化成功')
				this.loading = false

			} catch (error) {
				console.error('SDK初始化失败:', error)
				uni.showToast({
					title: 'SDK初始化失败: ' + error.message,
					icon: 'none',
					duration: 3000
				})
			}
		},

		setupPlayerEvents() {
			this.player
				?.on(PlayerEvents.play, () => {
					console.log('播放器开始播放')
					// 显示提示，让用户知道需要点击屏幕
					this.showPlayNotAllowedTip = true;
				})
				.on(PlayerEvents.waiting, () => {
					console.log('播放器等待中')
				})
				.on(PlayerEvents.playing, () => {
					console.log('播放器播放中')
				})
				.on(PlayerEvents.playNotAllowed, () => {
					console.log('需要用户交互才能播放')
					// 显示提示，让用户知道需要点击屏幕
					this.showPlayNotAllowedTip = true;
				})
		},

		setupSDKEvents() {
			this.avatarPlatform
				.on(SDKEvents.connected, (initResp) => {
					console.log('连接成功:', initResp)
				})
				.on(SDKEvents.stream_start, () => {
					console.log('开始推流')
				})
				.on(SDKEvents.frame_stop, () => {
					console.log('语音播报结束')
				})
				.on(SDKEvents.disconnected, (err) => {
					this.loading = false
					console.log('连接断开')
					if (err) {
						console.error('连接异常断开:', err)
					}
				})
				.on(SDKEvents.error, (error) => {
					console.error('SDK错误:', error)
					if (error.data) {
						console.error('错误详情:', error.data)
					}
				})
		},

		// 添加消息到列表
		addMessage(content, type = 'received') {
			this.chatMessages.push({
				content,
				type,
				timestamp: Date.now()
			})

			// 限制显示最近的20条消息
			if (this.chatMessages.length > 20) {
				this.chatMessages.shift()
			}

			// 滚动到底部
			this.$nextTick(() => {
				this.scrollTop = 9999
			})
		},

		// 发送文本消息
		async sendText() {
			if (!this.inputText.trim()) return

			try {
				// 添加发送的消息
				this.addMessage(this.inputText, 'sent')

				await this.avatarPlatform.writeText(this.inputText, {
					nlp: true,
					avatar_dispatch: {
						interactive_mode: 1
					},
					tdp: {
						orgCode: 'default',
						domain: 'general',
						function: 'chat'
					}
				})
				this.inputText = ''
			} catch (error) {
				console.error('发送文本失败:', error)
				uni.showToast({
					title: '发送失败',
					icon: 'none'
				})
			}
		},

		// 修改发送音频数据到百度API的方法
		async sendToBaiduAPI(audioBlob) {
			try {
				// 检测是否为Android设备
				const isAndroid = /android/i.test(navigator.userAgent);
				
				// 创建新的AudioContext
				const audioContext = new (window.AudioContext || window.webkitAudioContext)();
				const arrayBuffer = await audioBlob.arrayBuffer();
				const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);
				
				// 获取音频数据
				const inputData = audioBuffer.getChannelData(0);
				const inputSampleRate = audioBuffer.sampleRate;
				const outputSampleRate = 16000;
				
				// Android设备特殊处理：检测和移除重复数据
				let processedInputData;
				if (isAndroid) {
					// 检测重复模式
					const chunkSize = Math.floor(inputData.length / 2);
					let isRepeated = true;
					
					for (let i = 0; i < chunkSize; i++) {
						if (Math.abs(inputData[i] - inputData[i + chunkSize]) > 0.01) {
							isRepeated = false;
							break;
						}
					}
					
					if (isRepeated) {
						// 如果检测到重复，只使用前半部分数据
						processedInputData = inputData.slice(0, chunkSize);
						console.log('检测到重复数据，已移除重复部分');
					} else {
						processedInputData = inputData;
					}
				} else {
					processedInputData = inputData;
				}
				
				// 计算重采样后的数据长度
				const outputLength = Math.ceil(processedInputData.length * outputSampleRate / inputSampleRate);
				const outputData = new Float32Array(outputLength);
				
				// 使用更精确的重采样算法
				for (let i = 0; i < outputLength; i++) {
					const position = i * inputSampleRate / outputSampleRate;
					const index = Math.floor(position);
					const fraction = position - index;
					
					if (index >= processedInputData.length - 1) {
						outputData[i] = processedInputData[processedInputData.length - 1];
					} else {
						outputData[i] = (1 - fraction) * processedInputData[index] + 
									   fraction * processedInputData[index + 1];
					}
				}
				
				// Android设备特殊处理：应用噪声门限和去重过滤
				if (isAndroid) {
					const threshold = 0.01; // 噪声门限
					let lastValidSample = 0;
					
					for (let i = 0; i < outputData.length; i++) {
						// 应用噪声门限
						if (Math.abs(outputData[i]) < threshold) {
							outputData[i] = 0;
						}
						
						// 防止连续重复值
						if (Math.abs(outputData[i] - lastValidSample) < 0.001) {
							outputData[i] = outputData[i] * 0.9999; // 轻微变化
						}
						
						lastValidSample = outputData[i];
					}
				}
				
				// 音量归一化处理
				let maxAmplitude = 0;
				for (let i = 0; i < outputData.length; i++) {
					maxAmplitude = Math.max(maxAmplitude, Math.abs(outputData[i]));
				}
				
				const amplificationFactor = maxAmplitude < 0.1 ? 0.8 / maxAmplitude : 1;
				
				// 转换为PCM数据
				const pcmBuffer = new ArrayBuffer(outputData.length * 2);
				const pcmView = new DataView(pcmBuffer);
				
				for (let i = 0; i < outputData.length; i++) {
					const sample = outputData[i] * amplificationFactor;
					const pcm = Math.max(-32768, Math.min(32767, Math.round(sample * 32767)));
					pcmView.setInt16(i * 2, pcm, true);
				}
				
				// 检查数据有效性
				let nonZeroCount = 0;
				const checkView = new Int16Array(pcmBuffer);
				for (let i = 0; i < Math.min(1000, checkView.length); i++) {
					if (Math.abs(checkView[i]) > 500) {
						nonZeroCount++;
					}
				}
				
				if (nonZeroCount < 50) {
					console.warn('Low audio activity detected');
				}
				
				// 转换为Base64
				const bytes = new Uint8Array(pcmBuffer);
				let binaryString = '';
				for (let i = 0; i < bytes.length; i++) {
					binaryString += String.fromCharCode(bytes[i]);
				}
				this.base64Audio = btoa(binaryString);
				
				// 设置PCM长度
				this.pcmLength = pcmBuffer.byteLength;
				
				// 合理性检查
				if (!this.base64Audio || this.base64Audio.length < 100) {
					throw new Error('Invalid base64 data generated');
				}
				
				// 清理资源
				await audioContext.close();
				
				console.log('Audio processing stats:', {
					platform: isAndroid ? 'Android' : 'Other',
					originalLength: inputData.length,
					processedLength: processedInputData.length,
					resampledLength: outputLength,
					pcmLength: this.pcmLength,
					base64Length: this.base64Audio.length,
					maxAmplitude,
					amplificationFactor,
					nonZeroCount,
					sampleRate: outputSampleRate
				});
				
			} catch (error) {
				console.error('音频处理失败:', error);
				throw error;
			}
		},

		// 组件销毁时清理资源
		onUnload() {
			if (this.recorder) {
				this.recorder.stopRecord()
			}
			if (this.avatarPlatform) {
				this.avatarPlatform.destroy()
			}
			if (this.videoRecorder) {
				this.videoRecorder.stop()
				this.videoRecorder = null
			}
			if (this.isRecording) {
				this.stopScreenRecording()
			}
			if (this.stream) {
				this.stream.getTracks().forEach(track => track.stop());
			}
			if (this.mediaRecorder && this.isH5Recording) {
				this.stopH5Recording();
			}
			if (this.inactivityTimer) {
				clearTimeout(this.inactivityTimer);
			}
		},

		// 初始化视频录制器
		initVideoRecorder() {
			// #ifdef APP-PLUS || MP-WEIXIN
			this.videoRecorder = uni.createVideoRecorder()
			// #endif
		},

		// 修改 startVideoRecording 方法
		async startVideoRecording() {
			if (!this.stream) return;

			try {
				this.recordedChunks = [];
				
				// 设置录制事件处理
				this.mediaRecorder.ondataavailable = (event) => {
					if (event.data && event.data.size > 0) {
						this.recordedChunks.push(event.data);
					}
				};

				// 设置较短的时间片段，以确保数据能够正常保存
				const timeslice = 1000; // 每秒保存一次数据
				this.mediaRecorder.start(timeslice);
				this.isH5Recording = true;
				console.log('开始录制视频');

			} catch (error) {
				console.error('开始录制失败:', error);
				uni.showToast({
					title: '录制初始化失败',
					icon: 'none',
					duration: 2000
				});
			}
		},

		// 停止录制视频
		stopVideoRecording() {
			// #ifdef APP-PLUS || MP-WEIXIN
			if (!this.videoRecorder) return

			this.videoRecorder.stop({
				success: (res) => {
					console.log('视频录制成功:', res)
					this.videoPath = res.tempFilePath
					this.isRecording = false

					// 如果是最后一个问题，则上传视频
					if (this.currentQuestionIndex === this.questionList.length - 1) {
						this.uploadVideo()
					}
				},
				fail: (err) => {
					console.error('停止录制视频失败:', err)
					this.isRecording = false
					uni.showToast({
						title: '录制失败',
						icon: 'none'
					})
				}
			})
			// #endif
		},

		// 上传视频到服务器
		async uploadVideo() {
			if (!this.videoPath) {
				uni.showToast({
					title: '没有可上传的视频',
					icon: 'none'
				})
				return
			}

			uni.showLoading({
				title: '视频上传中...'
			})

			try {
				// 使用 $http 上传
				const uploadResult = await this.$http.post('/sys/common/upload', {
					file: this.videoPath,
					biz: 'ZJG'
				})

				console.log('视频上传成功:', uploadResult)
				uni.showToast({
					title: '上传成功',
					icon: 'success'
				})

			} catch (error) {
				console.error('视频上传失败1:', error)
				uni.showToast({
					title: '上传失败',
					icon: 'none'
				})
			} finally {
				uni.hideLoading()
			}
		},

		// 初始化屏幕录制器
		initScreenRecorder() {
			// #ifdef APP-PLUS
			const main = plus.android.runtimeMainActivity();
			const Context = plus.android.importClass('android.content.Context');
			const mediaProjectionManager = main.getSystemService(Context.MEDIA_PROJECTION_SERVICE);

			// 请求屏幕录制权限
			plus.android.requestPermissions(
				['android.permission.RECORD_AUDIO', 'android.permission.FOREGROUND_SERVICE'],
				function (resultObj) {
					if (resultObj.granted.length === 2) {
						console.log('获取录制权限成功');
					}
				},
				function (error) {
					console.error('获取权限失败:', error);
				}
			);
			// #endif
		},

		// 开始录制屏幕
		startScreenRecording() {
			// #ifdef APP-PLUS
			try {
				plus.screen.startRecording({
					format: 'mp4',
					videoScale: 1, // 视频缩放比例，1表示原始大小
					videoBitrate: 1.5 * 1024 * 1024, // 视频码率 1.5Mbps
					success: (res) => {
						console.log('开始录制屏幕');
						this.isRecording = true;
					},
					error: (error) => {
						console.error('开始录制失败:', error);
					}
				});
			} catch (error) {
				console.error('录制初始化失败:', error);
			}
			// #endif
		},

		// 停止录制屏幕
		stopScreenRecording() {
			// #ifdef APP-PLUS
			plus.screen.stopRecording({
				success: (res) => {
					console.log('录制成功:', res);
					this.videoPath = res.tempFilePath;
					this.isRecording = false;

					// 如果是最后一个问题，则上传视频
					if (this.currentQuestionIndex === this.questionList.length - 1) {
						this.uploadVideo();
					}
				},
				error: (error) => {
					console.error('停止录制失败:', error);
					this.isRecording = false;
					uni.showToast({
						title: '录制失败',
						icon: 'none'
					});
				}
			});
			// #endif
		},

		async initH5Recording() {
			try {
				this.stream = await navigator.mediaDevices.getDisplayMedia({
					video: true,
					audio: true
				});

				this.mediaRecorder = new MediaRecorder(this.stream);

				this.mediaRecorder.ondataavailable = (event) => {
					if (event.data.size > 0) {
						this.recordedChunks.push(event.data);
					}
				};

				this.mediaRecorder.onstop = () => {
					const blob = new Blob(this.recordedChunks, {
						type: 'video/mp4'
					});
					this.recordedVideoUrl = URL.createObjectURL(blob);
					this.uploadH5Video(blob);
				};

				// 自动开始录制
				this.startH5Recording();

			} catch (error) {
				console.error('初始化录制失败:', error);
				uni.showToast({
					title: '录制初始化失败',
					icon: 'none'
				});
			}
		},

		startH5Recording() {
			if (this.mediaRecorder && !this.isH5Recording) {
				this.recordedChunks = [];
				this.mediaRecorder.start();
				this.isH5Recording = true;
				console.log('开始H5录制');
			}
		},

		stopH5Recording() {
			if (this.mediaRecorder && this.isH5Recording) {
				this.mediaRecorder.stop();
				this.isH5Recording = false;
				this.stream.getTracks().forEach(track => track.stop());
				console.log('停止H5录制');
			}
		},

		toggleRecording() {
			if (!this.stream) {
				this.initCamera()
				return
			}

			if (this.isH5Recording) {
				console.log('停止录制')
				if (this.mediaRecorder && this.isH5Recording) {
					// 确保有数据可用
					this.mediaRecorder.requestData()
					this.mediaRecorder.stop()
					this.isH5Recording = false
					console.log('录制已停止')
					// 停止录制时关闭摄像头
					this.cleanupCamera()
				}
			} else {
				console.log('开始录制')
				this.startVideoRecording()
			}
		},

		// 修改 initCamera 方法，确保自动开始录制
		async initCamera() {
			try {
				console.log('正在请求摄像头权限...')
				
				// 检查是否是iOS设备
				const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
				
				// 针对iOS设备的特殊处理
				const constraints = {
					video: {
						width: { ideal: 160 },
						height: { ideal: 120 },
						facingMode: 'user'
					},
					audio: {
						echoCancellation: true, // 回声消除
						noiseSuppression: true, // 噪声抑制
						sampleRate: 44100,      // 采样率
						channelCount: 1         // 单声道
					}
				};

				// 先尝试获取媒体流
				try {
					this.stream = await navigator.mediaDevices.getUserMedia(constraints);
				} catch (err) {
					console.warn('完整媒体流获取失败，尝试只获取音频:', err);
					// 如果失败，尝试只获取音频（针对iOS）
					this.stream = await navigator.mediaDevices.getUserMedia({ audio: true });
				}

				// 创建视频预览元素（如果有视频流）
				if (this.stream.getVideoTracks().length > 0) {
					const videoPreview = document.createElement('video');
					videoPreview.className = 'video-preview';
					videoPreview.autoplay = true;
					videoPreview.muted = true;
					videoPreview.playsinline = true; // 重要：iOS需要这个属性
					videoPreview.setAttribute('webkit-playsinline', 'true'); // iOS旧版本支持
					videoPreview.srcObject = this.stream;

					const previewContainer = document.createElement('div');
					previewContainer.className = 'video-preview-container';
					previewContainer.appendChild(videoPreview);
					document.querySelector('.sp').appendChild(previewContainer);

					// 视频加载成功的回调
					videoPreview.onloadedmetadata = () => {
						console.log('视频预览已加载');
						videoPreview.play().catch(err => console.warn('自动播放失败:', err));
					};
				}

				// 初始化录制器
				const mimeType = this.getSupportedMimeType();
				const recorderOptions = {
					mimeType: mimeType,
					audioBitsPerSecond: 128000,
					videoBitsPerSecond: isIOS ? 1500000 : 2500000 // iOS使用较低的比特率
				};

				try {
					this.mediaRecorder = new MediaRecorder(this.stream, recorderOptions);
					console.log('录制器初始化成功，使用的MIME类型:', mimeType);
					this.startVideoRecording();
				} catch (err) {
					console.error('录制器初始化失败，尝试使用默认配置:', err);
					this.mediaRecorder = new MediaRecorder(this.stream);
					this.startVideoRecording();
				}

			} catch (error) {
				console.error('摄像头访问失败:', error);
				uni.showToast({
					title: '无法访问摄像头和麦克风，请确保已授予权限',
					icon: 'none',
					duration: 3000
				});
			}
		},

		// 添加新方法：获取支持的MIME类型
		getSupportedMimeType() {
			const types = [
				'video/webm;codecs=vp8,opus',
				'video/webm;codecs=vp9,opus',
				'video/webm;codecs=h264,opus',
				'video/mp4;codecs=h264,aac',
				'video/webm',
				'video/mp4'
			];

			for (const type of types) {
				if (MediaRecorder.isTypeSupported(type)) {
					return type;
				}
			}
			return '';
		},

		// 添加开始面试方法
		async startInterview() {
			// 获取 URL 参数
			
			console.log(this.urlParams, "this.urlParams.type")

			if (this.urlParams.type == 0) {
				// 验证必要参数
				if (!this.urlParams.qzid || !this.urlParams.subid) {
					uni.showToast({
						title: 'URL参数不完整',
						icon: 'none'
					});
					return;
				}
				this.isStarted = true;
				uni.showLoading({
					title: '正在初始化...'
				});

				// 尝试恢复播放器
				if (this.player) {
					try {
						await this.player.resume();
						console.log('播放器恢复成功');
					} catch (error) {
						console.error('播放器恢复失败:', error);
					}
				}

				AvatarPlatform.setLogLevel(1)
				try {
					await this.getWenti()
					await this.getxingxiang()
					await this.initAvatarSDK()
					await new Promise(resolve => setTimeout(resolve, 1000))
					// 再次尝试恢复播放器
					if (this.player) {
						try {
							await this.player.resume();
							console.log('播放器再次恢复成功');
						} catch (error) {
							console.error('播放器再次恢复失败:', error);
						}
					}
					await this.readNextQuestion()
				} catch (error) {
					console.error('初始化失败:', error)
					uni.showToast({
						title: '初始化失败，请重试',
						icon: 'none'
					})
				} finally {
					uni.hideLoading();
				}
			} else {
				// 验证必要参数
				if (!this.urlParams.qyid || !this.urlParams.msid || !this.urlParams.qzid || !this.urlParams.subid || !this.urlParams.jobid || !this.urlParams.posname) {
					uni.showToast({
						title: 'URL参数不完整',
						icon: 'none'
					});
					return;
				}
				this.isStarted = true;
				uni.showLoading({
					title: '正在初始化...'
				});

				// 尝试恢复播放器
				if (this.player) {
					try {
						await this.player.resume();
						console.log('播放器恢复成功');
					} catch (error) {
						console.error('播放器恢复失败:', error);
					}
				}

				AvatarPlatform.setLogLevel(1)
				try {
					await this.getWenti()
					await this.getxingxiang()
					await this.initAvatarSDK()
					await new Promise(resolve => setTimeout(resolve, 1000))
					// 再次尝试恢复播放器
					if (this.player) {
						try {
							await this.player.resume();
							console.log('播放器再次恢复成功');
						} catch (error) {
							console.error('播放器再次恢复失败:', error);
						}
					}
					await this.readNextQuestion()
					await this.initCamera()
				} catch (error) {
					console.error('初始化失败:', error)
					uni.showToast({
						title: '初始化失败，请重试',
						icon: 'none'
					})
				} finally {
					uni.hideLoading();
				}
			}
		},

		// 添加触摸事件处理
		mounted() {
			// 监听页面的触摸事件
			document.addEventListener('touchstart', () => {
				this.resumeAudioContext();
			}, { once: true }); // 只执行一次
		},

		// 添加获取 URL 参数的方法
		getUrlParams() {
			const url = window.location.href;
			const params = new URLSearchParams(url.split('?')[1]);

			this.urlParams = {
				qyid: params.get('qyid') || '',
				msid: params.get('msid') || '',
				qzid: params.get('qzid') || '',
				subid: params.get('subid') || '',
				jobid: params.get('jobid') || '',
				type: params.get('type') || '',
				posname:params.get('posname') || '',
			};

			console.log('URL参数:', this.urlParams);
		},

		// 添加重置定时器的方法
		resetInactivityTimer() {
			// 清除现有定时器
			if (this.inactivityTimer) {
				clearTimeout(this.inactivityTimer);
			}
			
			// 设置新的定时器
			this.inactivityTimer = setTimeout(() => {
				console.log('用户3秒未操作，关闭页面');
				// 关闭页面
				uni.navigateBack({
					delta: 1
				});
			}, this.inactivityTimeout);
		},

		// 在组件创建时启动定时器
		onShow() {
			this.resetInactivityTimer();
		},

		// 在组件销毁时清理定时器
		onUnload() {
			if (this.inactivityTimer) {
				clearTimeout(this.inactivityTimer);
			}
			// ... 其他清理代码
			if (this.stream) {
				this.stream.getTracks().forEach(track => track.stop())
			}
		},

		// 添加文本去重处理函数
		removeDuplicateText(text) {
			if (!text) return text;
			
			// 分割句子（考虑中文句号和英文句号）
			const sentences = text.split(/[.。]/);
			
			// 过滤空字符串并去除每个句子的首尾空格
			const cleanSentences = sentences
				.map(s => s.trim())
				.filter(s => s.length > 0);
			
			// 如果没有有效句子，返回原文本
			if (cleanSentences.length === 0) return text;
			
			// 去除重复句子
			const uniqueSentences = [...new Set(cleanSentences)];
			
			// 重新组合句子
			return uniqueSentences.join('。') + '。';
		},
	}
}
</script>

<style lang="scss" scoped>
.container {
	width: 100vw;
	height: 100vh;
	background: #000;
	position: relative;
}

.virtual-human-container {
	width: 100%;
	height: 100%;
	position: relative;
	overflow: hidden;

	.wrapper {
		position: absolute;
		top: 0;
		left: 0;
		width: 100%;
		height: 100%;
		display: flex;
		align-items: center;
		justify-content: center;
		color: white;
		font-size: 14px;
	}
}

.interaction-area {
	position: absolute;
	bottom: 40px;
	left: 0;
	right: 0;
	padding: 0 20px;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 20px;
	z-index: 100;

	.text-input {
		width: 100%;
		display: flex;
		gap: 10px;

		input {
			flex: 1;
			height: 40px;
			background: rgba(255, 255, 255, 0.2);
			border-radius: 20px;
			padding: 0 20px;
			color: white;
			font-size: 14px;

			&::placeholder {
				color: rgba(255, 255, 255, 0.5);
			}
		}

		button {
			width: 80px;
			height: 40px;
			background: #007AFF;
			color: white;
			border-radius: 20px;
			font-size: 14px;
			display: flex;
			align-items: center;
			justify-content: center;
		}
	}

	.voice-interaction {
		position: absolute;
		bottom: 40px;
		left: 50%;
		transform: translateX(-50%);
		display: flex;
		flex-direction: column;
		align-items: center;
		z-index: 101;

		.voice-icon {
			width: 60px;
			height: 60px;
			background-size: 30px;
			background-position: center;
			background-repeat: no-repeat;
			background-color: rgba(255, 255, 255, 0.2);
			border-radius: 50%;
			-webkit-touch-callout: none;
			-webkit-user-select: none;
			user-select: none;
			transition: all 0.3s;

			&.recording {
				background-color: rgba(0, 122, 255, 0.3);
				transform: scale(1.1);
			}
		}

		.voice-tip {
			color: white;
			font-size: 14px;
			margin-top: 10px;
			position: relative;
			z-index: 102;
		}
	}
}

.chat-list {
	position: absolute;
	top: 0;
	left: 0;
	width: 300px;
	height: 100%;
	// background: rgba(0, 0, 0, 0.5);
	z-index: 97;

	.scroll-area {
		height: 100%;
		padding: 20px;
	}

	.message-item {
		margin-bottom: 15px;
		max-width: 80%;

		&.sent {
			margin-left: auto;

			.message-content {
				background: #007AFF;
				color: white;
				border-radius: 15px 15px 0 15px;
			}
		}

		&.received {
			margin-right: auto;

			.message-content {
				background: rgba(255, 255, 255, 0.9);
				color: #333;
				border-radius: 15px 15px 15px 0;
			}
		}

		.message-content {
			display: inline-block;
			padding: 8px 12px;
			font-size: 14px;
			word-break: break-all;
		}
	}
}

.preview-area {
	position: fixed;
	top: 20px;
	right: 10px;
	z-index: 99;
	display: flex;
	flex-direction: column;
	gap: 10px;
	align-items: flex-end;
}

.record-controls {
	margin-top: 10px;

	.record-btn {
		padding: 8px 16px;
		font-size: 14px;
		border: none;
		border-radius: 4px;
		background: rgba(255, 255, 255, 0.2);
		color: white;
		cursor: pointer;
		transition: all 0.3s;

		&.recording {
			background: rgba(255, 0, 0, 0.5);
		}

		&:hover {
			opacity: 0.8;
		}
	}
}

.video-preview-container {
	width: 160px;
	height: 120px;
	background: #000;
	border-radius: 8px;
	overflow: hidden;

	.video-preview {
		width: 100%;
		height: 100%;
		object-fit: cover;
		transform: scaleX(-1);
	}
}

.sp {
	width: 160px;
	height: 120px;
}

// 添加蒙版和按钮样式
.start-mask {
	position: fixed;
	top: 0;
	left: 0;
	right: 0;
	bottom: 0;
	background: rgba(0, 0, 0, 0.7);
	z-index: 999;
	display: flex;
	align-items: center;
	justify-content: center;
}

.start-btn {
	padding: 12px 30px;
	font-size: 18px;
	color: #fff;
	background: rgba(255, 255, 255, 0.2);
	border: 2px solid rgba(255, 255, 255, 0.5);
	border-radius: 25px;
	transition: all 0.3s;

	&:active {
		transform: scale(0.95);
		background: rgba(255, 255, 255, 0.3);
	}
}

.start-tips {
	position: absolute;
	top: 40%;
	left: 50%;
	transform: translateX(-50%);
	color: #fff;
	font-size: 16px;
	text-align: center;
	padding: 10px 20px;
	background: rgba(0, 0, 0, 0.5);
	border-radius: 4px;
	margin-bottom: 20px;
}
</style>